package com.sky.service.impl;

import com.sky.entity.Goods;
import com.sky.entity.OrderDetail;
import com.sky.entity.Orders;
import com.sky.mapper.OrderDetailMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.ReportService;
import com.sky.service.WorkspaceService;
import com.sky.vo.*;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collector;

@Service
public class ReportServiceImpl implements ReportService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WorkspaceService workspaceService;

    @Override
    public TurnoverReportVO reportTurnover(LocalDate begin, LocalDate end) {
        LocalDate current = begin;
        List<String> dateList = new ArrayList<>();
        List<String> turnoverList = new ArrayList<>();

        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);
        List<Orders> ordersList = orderMapper.getByStatusAndBeginAndEnd(beginTime, endTime);

        Integer index = 0;
        while (true) {
            dateList.add(current.toString());
            LocalDateTime min = LocalDateTime.of(current, LocalTime.MIN);
            LocalDateTime max = LocalDateTime.of(current, LocalTime.MAX);
            Double sum = 0.0;
            while(index < ordersList.size()
                    && ordersList.get(index).getOrderTime().isAfter(min)
                    && ordersList.get(index).getOrderTime().isBefore(max)) {
                sum += ordersList.get(index).getAmount().doubleValue();
                index++;
            }
            turnoverList.add(sum.toString());

            if(current.equals(end)) break;
            current = current.plusDays(1);
        }
        return TurnoverReportVO.builder()
                .dateList(String.join(",", dateList))
                .turnoverList(String.join(",", turnoverList))
                .build();
    }

    @Override
    public UserReportVO reportUser(LocalDate begin, LocalDate end) {
        LocalDate current = begin;
        List<String> dateList = new ArrayList<>();
        List<String> totalUserList = new ArrayList<>();
        List<String> newUserList = new ArrayList<>();

        LocalDateTime endTime = LocalDateTime.of(begin.plusDays(-1), LocalTime.MAX);

        Long last = userMapper.countByEndTime(endTime);

        while (true) {
            dateList.add(current.toString());
            LocalDateTime max = LocalDateTime.of(current, LocalTime.MAX);

            Long total = userMapper.countByEndTime(max);
            totalUserList.add(total.toString());

            Long different = total - last;
            newUserList.add(Long.toString(different));

            last = total;
            if(current.equals(end)) break;
            current = current.plusDays(1);
        }
        return UserReportVO.builder()
                .dateList(String.join(",", dateList))
                .totalUserList(String.join(",", totalUserList))
                .newUserList(String.join(",", newUserList))
                .build();
    }

    @Override
    public OrderReportVO reportOrder(LocalDate begin, LocalDate end) {
        LocalDate current = begin;
        List<String> dateList = new ArrayList<>();
        List<String> orderCountList = new ArrayList<>();
        List<String> validOrderCountList = new ArrayList<>();
        Integer totalOrderCount = 0;
        Integer validOrderCount = 0;
        Double orderCompletionRate = 0.0;

        while (true) {
            dateList.add(current.toString());
            LocalDateTime min = LocalDateTime.of(current, LocalTime.MIN);
            LocalDateTime max = LocalDateTime.of(current, LocalTime.MAX);

            Map map = new HashMap();
            map.put("begin", min);
            map.put("end", max);

            Integer total = orderMapper.countByMap(map);
            orderCountList.add(total.toString());
            totalOrderCount += total;

            map.put("status", Orders.COMPLETED);
            Integer valid = orderMapper.countByMap(map);
            validOrderCountList.add(valid.toString());
            validOrderCount += valid;

            if(current.equals(end)) break;
            current = current.plusDays(1);
        }
        orderCompletionRate = (double) validOrderCount / totalOrderCount;

        return OrderReportVO.builder()
                .dateList(String.join(",", dateList))
                .orderCountList(String.join(",", orderCountList))
                .validOrderCountList(String.join(",", validOrderCountList))
                .totalOrderCount(totalOrderCount)
                .validOrderCount(validOrderCount)
                .orderCompletionRate(orderCompletionRate)
                .build();
    }

    @Override
    public SalesTop10ReportVO reportTop10(LocalDate begin, LocalDate end) {
        List<String > nameList = new ArrayList<>();
        List<String> numberList = new ArrayList<>();

        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);

        List<Goods> GoodsList = orderMapper.getTop10(beginTime, endTime);

        for(Goods goods : GoodsList) {
            nameList.add(goods.getName());
            numberList.add(goods.getCount().toString());
        }

        return SalesTop10ReportVO.builder()
                .nameList(String.join(",", nameList))
                .numberList(String.join(",", numberList))
                .build();
    }

    @Override
    public void export(HttpServletResponse response) {
        LocalDate begin = LocalDate.now().minusDays(30);
        LocalDate end = LocalDate.now().minusDays(1);
        LocalDateTime beginTime = LocalDateTime.of(begin, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(end, LocalTime.MAX);

        //查询概览数据
        BusinessDataVO businessDataVO = workspaceService.getBusinessData(beginTime, endTime);

        //通过POI将数据写入excel文件中
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");
//        URL resourceUrl = this.getClass().getClassLoader().getResource("template/运营数据报表模板.xlsx");
//        System.out.println(resourceUrl);
        try {
            //基于模板创建一个新的excel文件
            XSSFWorkbook excel = new XSSFWorkbook(in);
            in.close();

            XSSFSheet sheet = excel.getSheet("Sheet1");

            //填充数据-时间
            sheet.getRow(1).getCell(1).setCellValue("时间" + begin + "至" + end);

            //获取第四行对象
            XSSFRow row = sheet.getRow(3);
            row.getCell(2).setCellValue(businessDataVO.getTurnover());
            row.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());
            row.getCell(6).setCellValue(businessDataVO.getNewUsers());

            //第五行
            row = sheet.getRow(4);
            row.getCell(2).setCellValue(businessDataVO.getValidOrderCount());
            row.getCell(4).setCellValue(businessDataVO.getUnitPrice());

            LocalDate current = begin;
            for(int i = 7; i < 37; i++) {
                beginTime = LocalDateTime.of(current, LocalTime.MIN);
                endTime = LocalDateTime.of(current, LocalTime.MAX);

                businessDataVO = workspaceService.getBusinessData(beginTime, endTime);

                row = sheet.getRow(i);
                row.getCell(1).setCellValue(current.toString());
                row.getCell(2).setCellValue(businessDataVO.getTurnover());
                row.getCell(3).setCellValue(businessDataVO.getValidOrderCount());
                row.getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());
                row.getCell(5).setCellValue(businessDataVO.getUnitPrice());
                row.getCell(6).setCellValue(businessDataVO.getNewUsers());

                current = current.plusDays(1);
            }

            //把excel文件下载到客户端浏览器
            OutputStream out = response.getOutputStream();
            excel.write(out);

            out.close();
            excel.close();;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}


